package com.sunsharing.common.anno;

import org.apache.log4j.Logger;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * Created with IntelliJ IDEA.
 * User: criss
 * Date: 13-4-25
 * Time: 下午4:28
 * To change this template use File | Settings | File Templates.
 */
public class AnoClassCretator {

    Logger logger = Logger.getLogger(AnoClassCretator.class);

    List<Class> classes = new ArrayList<Class>();

    Map<Class,Map<String,Class>> cache = new ConcurrentHashMap<Class, java.util.Map<String, Class>>();

    private AnoClassCretator()
    {

    }

    static AnoClassCretator instance = new AnoClassCretator();
    public static AnoClassCretator getInstance()
    {
         return instance;
    }
    public Object createObject(Class cls,String key)
    {
        return createObject(cls,key,null,null);
    }
    public Object createObject(Class cls,String key,Class[]types,Object[]objs)
    {
        Map<String,Class> clss = cache.get(cls);
        if(classes.size()==0)
        {
            loadAllClasses();
        }
        if(clss==null)
        {
            clss = new HashMap<String,Class>();
            for (Class<?> c : classes) {
                if (cls.isAssignableFrom(c) && !cls.equals(c)) {
                    //clss.add(c);
                    //获取注解
                    Factory fac = c.getAnnotation(Factory.class);
                    if(fac!=null)
                    {
                        clss.put(fac.key(),c);
                    }
                }
            }
            cache.put(cls,clss);
        }
        Class objcls = cache.get(cls).get(key);
        if(objs==null)
        {
            try
            {
                return objcls.newInstance();
            }catch (Exception e)
            {
                logger.error("初始化失败",e);
                throw new RuntimeException("初始化"+clss+"["+key+"]失败");
            }
        } else
        {
            try
            {
                Constructor c1=objcls.getDeclaredConstructor(types);
                return c1.newInstance(objs);
            }catch (Exception e)
            {
                logger.error("初始化失败",e);
                throw new RuntimeException("初始化"+clss+"["+key+"]失败");
            }
        }


    }

    public synchronized  void loadAllClasses()
    {
        String path = System.getProperty("java.class.path");
        String seperate = "";
        if(path.indexOf(":")!=-1)
        {
            seperate = ":";
        } else
        {
            seperate = ";";
        }
        String [] arrs = path.split(seperate);
        for(int i=0;i<arrs.length;i++)
        {
            if(arrs[i].endsWith("classes"))
            {
                //目录
                readPath(arrs[i]);
            }else
            {
                //jar
                if(arrs[i].startsWith("common.")||
                   arrs[i].startsWith("container.")||
                   arrs[i].startsWith("dispatch.")||
                   arrs[i].startsWith("transport.")||
                   arrs[i].startsWith("wsdlcall.")||
                   arrs[i].startsWith("flow."))
                {
                    readJar(arrs[i]);
                }
            }
        }
    }

    private void readPath(String path)
    {
        File tmp = new File(path);
        if(tmp.exists())
        {
            if(tmp.isFile())
            {
                String t = tmp.getAbsolutePath();
                if(t.endsWith("class"))
                {
                    int index = t.indexOf("class");
                    t = t.substring(index+8,t.length());
                    t = t.replaceAll("/","\\.").substring(0,t.length()-6);
                    try
                    {
                        classes.add(Class.forName(t));
                    }catch (Exception e)
                    {
                        logger.error("加载类失败",e);
                    }
                }
            }else
            {
                File[] list = tmp.listFiles();
                if(list!=null)
                {
                    for(int i=0;i<list.length;i++)
                    {
                        readPath(list[i].getAbsolutePath());
                    }
                }
            }
        }
    }
    private void readJar(String path)
    {
        try
        {
            JarFile jarFile = new JarFile(path);
            Enumeration en = jarFile.entries();
            while (en.hasMoreElements()) {
                JarEntry jarEntry = (JarEntry)en.nextElement();
                String t = (jarEntry.getName());
                if(t.endsWith("class"))
                {
                    int i = t.lastIndexOf("/");
                    String name = t.substring(i+1,t.length()-6);
                    t = t.replaceAll("/","\\.").substring(0,t.length()-6);
                    try
                    {
                        classes.add(Class.forName(t));
                    } catch (Exception e2)
                    {
                        logger.error("加载类失败",e2);
                    }

                }
            }
        }catch (Exception e)
        {
            logger.error("读取Jar出错",e);
            throw new RuntimeException("读取Jar出错");
        }
    }

}
